<template>
  <div class="timeline-story-stickybar" ref="wrapper">
    <ul class="stickybar__list" ref="listRef" @scroll="onListScroll">
      <div
        class="stickybar__nav__prev"
        v-show="showNavPrev"
        @click="scrollBtnHandller('prev')"
      ></div>
      <li
        v-for="(tab, idx) in list"
        :key="tab.id"
        class="stickybar__item"
        :class="[{ 'is-active': currentIdx >= Number(idx) }]"
      >
        <div
          class="stickybar__btn"
          :class="[{ 'is-active': currentIdx == Number(idx) }]"
          @click="updateCurrentIdx(Number(idx))"
        >
          {{ tab.title }}
        </div>
        <span
          class="stickybar__btn__line"
          :class="[{ 'is-active': currentIdx > Number(idx) }]"
        ></span>
      </li>
      <div
        class="stickybar__nav__next"
        v-show="showNavNext"
        @click="scrollBtnHandller('next')"
      ></div>
    </ul>
    <div
      class="stickybar__line"
      :style="{
        width: `${currentTabPos - 12}px`,
        transition: hasTransition ? 'width .25s linear' : '',
      }"
    ></div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'

// 定义组件名称
defineOptions({
  name: 'TimelineStoryStickybar'
})

const props = defineProps<{
  list: any[]
  currentIdx: number
}>()

// 定义 emits
const emit = defineEmits<{
  updateCurrentIdx: [idx: number]
}>()

// 响应式数据
const scrollLeft = ref(0)
const lastBtnRight = ref(0)
const currentTabPos = ref(0)
const listLeft = ref(0)
const hasTransition = ref(false)
const vsWidth = ref(typeof window === 'undefined' ? 1024 : window.innerWidth)

// 模板引用
const wrapper = ref<HTMLElement | null>(null)
const listRef = ref<HTMLElement | null>(null)

// 计算属性
const showNavPrev = computed(() => {
  return scrollLeft.value > 40
})

const showNavNext = computed(() => {
  return lastBtnRight.value - 40 > vsWidth.value
})

// 监听器
watch(() => vsWidth.value, () => {
  onListScroll()
  calListLeft()
})

watch(() => props.currentIdx, () => {
  nextTick(centerTheList)
})

// 方法
const updateViewportSize = () => {
  if (typeof window === 'undefined') return
  vsWidth.value = window.innerWidth
}

const onListScroll = () => {
  hasTransition.value = true
  updateLine()
  setShowNav()
}

const calListLeft = () => {
  const target = listRef.value
  if (target) {
    listLeft.value = (vsWidth.value - target.getBoundingClientRect().width) / 2
  }
}

const updateCurrentIdx = (idx: number) => {
  emit('updateCurrentIdx', idx)
}

const setShowNav = () => {
  const listEl = listRef.value
  if (listEl) {
    scrollLeft.value = listEl.scrollLeft
  }

  // 获取最后一个按钮的位置
  const buttons = listEl?.querySelectorAll('.stickybar__btn')
  if (buttons && buttons.length > 0) {
    const lastBtn = buttons[buttons.length - 1] as HTMLElement
    lastBtnRight.value = lastBtn.getBoundingClientRect().right
  }
}

const scrollBtnHandller = (dir: string) => {
  const listEl = listRef.value
  if (!listEl) return

  if (dir === 'next') {
    listEl.scrollLeft += 100
  } else {
    listEl.scrollLeft -= 100
  }
}

const updateLine = () => {
  const buttons = listRef.value?.querySelectorAll('.stickybar__btn')
  if (!buttons) return

  const currentTab = buttons[Number(props.currentIdx)] as HTMLElement
  if (!currentTab) return

  currentTabPos.value = currentTab.getBoundingClientRect().right
}

const centerTheList = () => {
  const buttons = listRef.value?.querySelectorAll('.stickybar__btn')
  if (!buttons) return

  const currentTab = buttons[Number(props.currentIdx)] as HTMLElement
  if (!currentTab) return

  const tabHalfWidth = currentTab.clientWidth / 2
  const center = vsWidth.value / 2
  hasTransition.value = false

  nextTick(() => {
    const listEl = listRef.value
    if (listEl) {
      listEl.scrollLeft -= center - currentTab.getBoundingClientRect().right + tabHalfWidth
      setTimeout(onListScroll, 100)
    }
  })
}

// 生命周期钩子
onMounted(() => {
  if (typeof window !== 'undefined') {
    window.addEventListener('resize', updateViewportSize)
    updateViewportSize()
  }

  nextTick(() => {
    setTimeout(onListScroll, 300)
    calListLeft()
  })
})
</script>

<style lang="scss" scoped>
.timeline-story-stickybar {
  display: flex;
  justify-content: center;
  height: 100%;
  position: relative;
  z-index: 1;

  .stickybar__list {
    display: flex;
    align-items: center;
    overflow-x: scroll;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;

    &::-webkit-scrollbar {
      display: none;
    }
  }

  .stickybar__item {
    display: flex;
    align-items: center;

    &:not(:first-of-type) {
      margin-left: 0;
    }

    &:last-of-type {
      .stickybar__btn {
        &__line {
          display: none;
        }
      }
    }

    &.is-active {
      .stickybar__btn {
        color: #0066cc;
        font-size: 18px;
        font-weight: 600;
        line-height: 1.3;
      }
    }
  }

  .stickybar__btn {
    width: auto;
    border: none;
    background: none;
    white-space: nowrap;
    color: #666;
    font-size: 14px;
    line-height: 1.4;
    text-decoration: none;
    padding: 16px 12px 12px;
    cursor: pointer;
    transition: color 0.2s ease-in-out;
    background-color: #f8f9fa;

    &__line {
      width: 12px;
      height: 1px;
      background: #666;
      transform: translateY(3px);

      &.is-active {
        background: #0066cc;
      }
    }
  }

  .stickybar__nav {
    &__prev,
    &__next {
      position: absolute;
      width: 28px;
      height: 100%;
      background-color: #f8f9fa;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 1;
      cursor: pointer;

      &::after {
        content: '';
        width: 14px;
        height: 14px;
        background-image: url('');
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
      }
    }

    &__prev {
      left: -1px;

      &::after {
        transform: scale(-1);
      }
    }

    &__next {
      right: -1px;
    }
  }

  .stickybar__line {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    background-color: #0066cc;
    z-index: 1;
  }
}
</style>